import {
  BadRequestException,
  CallHandler,
  ExecutionContext,
  Injectable,
  NestInterceptor,
} from '../common'

import multer from 'multer'
import { Request, Response, NextFunction } from 'express'
import { MulterConfigService } from './multer-config.service'

/**
 * 单个文件上传拦截器
 * @param fieldName 文件名
 */
export function FileInterceptor(fieldName: string) {
  @Injectable()
  class FileInterceptor implements NestInterceptor {
    // 依赖注入 获取全局配置的上传文件配置
    constructor(private readonly multerConfigService: MulterConfigService) {}

    async intercept(context: ExecutionContext, next: CallHandler) {
      const request = context.switchToHttp().getRequest<Request>() // 获取请求对象
      const response = context.switchToHttp().getResponse<Response>() // 获取响应对象
      // 获取文件上传中间件 upload
      const upload = this.multerConfigService.getMulterInstance().single(fieldName)
      //  等待 promise 完成才会往下面继续走
      await new Promise<void>((resolve, reject) => {
        // 执行中间件 文件上传后会给请求对象扩展一个 file 属性 其中值是 multer 上传的文件
        upload(request, response, (error) => {
          error ? reject(error) : resolve()
        })
      })
      //  异步上传后再执行 next.handle 继续往后面执行处理请求
      return next.handle()
    }
  }
  return FileInterceptor
}

/**
 * 一个字段多个文件上传拦截器
 */
export function FilesInterceptor(fieldName: string, maxCount?: number) {
  @Injectable()
  class FilesInterceptor implements NestInterceptor {
    constructor(
      private readonly multerConfigService: MulterConfigService,
    ) {}
    async intercept(context: ExecutionContext, next: CallHandler) {
      const request = context.switchToHttp().getRequest<Request>() // 获取请求对象
      const response = context.switchToHttp().getResponse<Response>() // 获取响应对象
      // 获取文件上传中间件 upload
      const upload = this.multerConfigService.getMulterInstance().array(fieldName, maxCount)
      //  等待 promise 完成才会往下面继续走
      await new Promise<void>((resolve, reject) => {
        // 执行中间件 文件上传后会给请求对象扩展一个 file 属性 其中值是 multer 上传的文件
        upload(request, response, (error) => {
          error ? reject(error) : resolve()
        })
      })
      //  异步上传后再执行 next.handle 继续往后面执行处理请求
      return next.handle()
    }
  }
  return FilesInterceptor
}


/**
 * 多个字段 多个文件上传
 */
export function FileFieldsInterceptor(uploadFields) {
  @Injectable()
  class FileFieldsInterceptor implements NestInterceptor {
    constructor(
      private readonly multerConfigService: MulterConfigService,
    ){}
    async intercept(context: ExecutionContext, next: CallHandler) {
      const request = context.switchToHttp().getRequest<Request>() // 获取请求对象
      const response = context.switchToHttp().getResponse<Response>() // 获取响应对象
      // 获取文件上传中间件 upload
      const upload = this.multerConfigService.getMulterInstance().fields(uploadFields)
      //  等待 promise 完成才会往下面继续走
      await new Promise<void>((resolve, reject) => {
        // 执行中间件 文件上传后会给请求对象扩展一个 file 属性 其中值是 multer 上传的文件
        upload(request, response, (error) => {
          error ? reject(error) : resolve()
        })
      })
      //  异步上传后再执行 next.handle 继续往后面执行处理请求
      return next.handle()
    }
  }
  return FileFieldsInterceptor
}



/**
 * 多个字段 多个文件上传
 */
export function AnyFilesInterceptor() {
  @Injectable()
  class AnyFilesInterceptor implements NestInterceptor {
    constructor(
      private readonly multerConfigService: MulterConfigService,
    ) {}
    async intercept(context: ExecutionContext, next: CallHandler) {
      const request = context.switchToHttp().getRequest<Request>() // 获取请求对象
      const response = context.switchToHttp().getResponse<Response>() // 获取响应对象
      // 获取文件上传中间件 upload
      const upload = this.multerConfigService.getMulterInstance().any()
      //  等待 promise 完成才会往下面继续走
      await new Promise<void>((resolve, reject) => {
        // 执行中间件 文件上传后会给请求对象扩展一个 file 属性 其中值是 multer 上传的文件
        upload(request, response, (error) => {
          error ? reject(error) : resolve()
        })
      })
      //  异步上传后再执行 next.handle 继续往后面执行处理请求
      return next.handle()
    }
  }
  return AnyFilesInterceptor
}


/**
 * 多个字段 多个文件上传
 */
export function NoFilesInterceptor() {
  @Injectable()
  class NoFilesInterceptor implements NestInterceptor {
    constructor(
      private readonly multerConfigService: MulterConfigService,
    ) {}
    async intercept(context: ExecutionContext, next: CallHandler) {
      const request = context.switchToHttp().getRequest<Request>() // 获取请求对象
      const response = context.switchToHttp().getResponse<Response>() // 获取响应对象
      // 获取文件上传中间件 upload
      const upload = this.multerConfigService.getMulterInstance().any()
      //  等待 promise 完成才会往下面继续走
      await new Promise<void>((resolve, reject) => {
        // 执行中间件 文件上传后会给请求对象扩展一个 file 属性 其中值是 multer 上传的文件
        upload(request, response, (error) => {
          error ? reject(error) : resolve()
        })
      })
      if(request.file || request.files) throw new BadRequestException(`不允许上传文件`)
      //  异步上传后再执行 next.handle 继续往后面执行处理请求
      return next.handle()
    }
  }
  return NoFilesInterceptor
}
